﻿using System;
using System.Collections.Generic;
using FlowCanvas.Nodes;
using GameFramework.Battle.Core;
using Gameplay.PVE.Utils;
using RootMotion.FinalIK;
using UnityEditor;
using UnityEngine;
using Random = System.Random;

namespace Gameplay.PVE.Survivor
{
    public class GpuSkinningWeapon: MonoBehaviour
    {
        public List<GpuSkinningWeaponData> weaponList = new List<GpuSkinningWeaponData>();
        
        public static Vector3 PosFromMat4(in Matrix4x4 m)
        {
            float x = m.m03;
            float y = m.m13;
            float z = m.m23;
            return new Vector3(x, y, z);
        }

        public static Quaternion RotFromMat4(in Matrix4x4 matrix)
        {
            Vector3 forward;
            forward.x = matrix.m02;
            forward.y = matrix.m12;
            forward.z = matrix.m22;

            Vector3 upwards;
            upwards.x = matrix.m01;
            upwards.y = matrix.m11;
            upwards.z = matrix.m21;

            return Quaternion.LookRotation(forward, upwards).normalized;
        }

        public static Vector3 ScaleFromMat4(in Matrix4x4 matrix)
        {
            Vector3 scale;
            scale.x = new Vector3(matrix.m00, matrix.m01, matrix.m02).magnitude;
            scale.y = new Vector3(matrix.m10, matrix.m11, matrix.m12).magnitude;
            scale.z = new Vector3(matrix.m20, matrix.m21, matrix.m22).magnitude;
            return scale;
        }

        public static void SetTransformByMatrix(Transform trans, in Matrix4x4 matrix)
        {
            trans.position = PosFromMat4(matrix);
            trans.rotation = RotFromMat4(matrix);
            trans.localScale = ScaleFromMat4(matrix);
        }

        public void ResetTPos()
        {
            /*var oriMatrix = transform.localToWorldMatrix;
            transform.position = Vector3.zero;
            transform.rotation = Quaternion.identity;
            transform.localScale = Vector3.one;

            var skinnedMeshRenderer = GetComponentsInChildren<SkinnedMeshRenderer>();
            for (int i = 0; i < skinnedMeshRenderer.Length; i++)
            {
                var skin = skinnedMeshRenderer[i];
                for (int j = 0; j < skin.bones.Length; j++)
                {
                    SetTransformByMatrix(skin.bones[j], skin.sharedMesh.bindposes[j].inverse);
                }
                SetTransformByMatrix(transform, oriMatrix);
            }*/
#if UNITY_EDITOR
            var skinnedMeshRenderer = GetComponentsInChildren<SkinnedMeshRenderer>();
            for (int i = 0; i < skinnedMeshRenderer.Length; i++)
            {
                if (skinnedMeshRenderer[i].rootBone.name.Contains("Weapon") || skinnedMeshRenderer[i].rootBone.name.Contains("Prop1"))
                {
                    continue;
                }

                var mesh = skinnedMeshRenderer[i].sharedMesh;
                var path = AssetDatabase.GetAssetPath(mesh);
                var importer = AssetImporter.GetAtPath(path) as ModelImporter;
                if (importer.optimizeGameObjects)
                {
                    importer.optimizeGameObjects = true;
                    AssetDatabase.WriteImportSettingsIfDirty(path);
                    AssetDatabase.SaveAssets();
                    AssetDatabase.Refresh();
                }
                var asset = AssetDatabase.LoadAssetAtPath<GameObject>(path);
                var root = FindChild(asset.transform,"Root");
                var selfRoot = FindChild(transform, "Root");
                CopyTransform(root, selfRoot);
            }
#endif
        }

        private void CopyTransform(Transform from, Transform target)
        {
            //对于每一个target中的节点，在From中找到同样路径的节点，并将From中的位置赋值给target
            for (int i = 0; i < target.childCount; i++)
            {
                var targetChild = target.GetChild(i);
                var childPath = targetChild.name;
                var child = from.Find(childPath);
                if (child)
                {
                    targetChild.localPosition = child.localPosition;
                    targetChild.localRotation = child.localRotation;
                    targetChild.localScale = child.localScale;
                    CopyTransform(child, targetChild);
                }
            }
        }
        
        public bool Contains(Transform point)
        {
            for (int i = 0; i < weaponList.Count; i++)
            {
                if (FindChild(weaponList[i].point, point.name))
                {
                    return true;
                }
            }
            return false;
        }
        
        public void FindWeapon()
        {
            weaponList.Clear();
            var skinnedMeshRenderers = GetComponentsInChildren<SkinnedMeshRenderer>();
            for (int i = 0; i < skinnedMeshRenderers.Length; i++)
            {
                var skinnedMeshRenderer = skinnedMeshRenderers[i];
                if (skinnedMeshRenderer.rootBone.name.Contains("Weapon") || skinnedMeshRenderer.rootBone.name.Contains("Prop1"))
                {
                    var parent = skinnedMeshRenderer.rootBone.transform;
                    var point = parent;
                    while (parent != null)
                    {
                        if (parent.name.Contains("Bip"))
                        {
                            point = parent;
                            break;
                        }
                        parent = parent.parent;
                    }
                    weaponList.Add(new GpuSkinningWeaponData
                    {
                        point = point,
                        weapon = skinnedMeshRenderer,
                    });
                    FindKeyPoints(weaponList[^1]);
                    return;
                }
            }
            
            //寻找名字带有Weapon的节点
            var weapon = FindChild(transform, "Weapon",true);
            if (weapon == null)
            {
                weapon = FindChild(transform, "Prop1",true);
            }
            if (weapon != null)
            {
                var renderer = weapon.GetComponentInChildren<Renderer>();
                if (renderer)
                {
                    var point = weapon.transform;
                    var parent = weapon.transform;
                    while (parent != null)
                    {
                        if (parent.name.Contains("Bip"))
                        {
                            point = parent;
                            break;
                        }
                        parent = parent.parent;
                    }
                    weaponList.Add(new GpuSkinningWeaponData
                    {
                        weapon = renderer,
                        point = point,
                    });
                    FindKeyPoints(weaponList[^1]);
                }
            }
        }

        private void FindKeyPoints(GpuSkinningWeaponData data)
        {
            var gunPoint = FindChild(data.point, "GunPoint",true);
            if (gunPoint != null)
            {
                data.keyPoints.Add(gunPoint);
            }
        }
        
        public static Transform FindChild(Transform trans, string goName,bool contains = false)
        {
            if (trans.name == goName)
            {
                return trans;
            }
            Transform child = trans.Find(goName);
            if (child != null)
                return child;
 
            Transform go = null;
            for (int i = 0; i < trans.childCount; i++)
            {
                child = trans.GetChild(i);
                if (contains && child.name.Contains(goName))
                {
                    return child;
                }
                go = FindChild(child, goName,contains);
                if (go != null)
                    return go;
            }
            return null;
        }
    }

    [Serializable]
    public class GpuSkinningWeaponData
    {
        public Renderer weapon;
        public Transform point;
        public List<Transform> keyPoints = new List<Transform>();
    }
}
